﻿/*********************************
 * 视频分析客流统计系统
 * 魏继琼
 * 2011年10月6日18:24:30
 * 
 * ******************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AForge.Video.DirectShow;
using AForge.Video;
using System.Threading;
using AForge.Vision.Motion;
using VideoFlowStatistics.Class;
using VideoFlowStatistics.EntityClass;
using AForge.Imaging;
using AForge.Video.VFW;


namespace VideoFlowStatistics
{
    public partial class MainForm : Form
    {
        //视频源
        private IVideoSource videoSource = null;

        //历史数据分析
        private List<float> motionHistory = new List<float>();

        //运行分析
        BlobCountingObjectsProcessing monBlob = new BlobCountingObjectsProcessing();
        MotionDetector detector;

        //总人数
        private int[] AllCount = new int[] { };
        private int[] tmpAllCount = new int[] { };

        //分辨率设置
        int wpx = Properties.Settings.Default.GridWidth;
        int hpx = Properties.Settings.Default.GridHeight;
        //运动级别最低值
        float motionAmount = Properties.Settings.Default.MotionAmount;

        //运动分析
        FeatureAnalysis fAnalysis;

        //运动检测和处理算法分类选择
        private int motionDetectionType = 1;
        private int motionProcessingType = 1;

        private AVIWriter writer = null;
        private static DateTime StartTime = new DateTime();

        /// <summary>
        /// 撞线区域特征集合
        /// </summary>
        private Dictionary<string, CAreaFeature> LineAreaFeature
        {
            get;
            set;
        }
        
        private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();

        //每帧物体的特征
        private Blob[] RecBlobItems;


        public MainForm()
        {
            InitializeComponent();
            detector = new MotionDetector(
           new SimpleBackgroundModelingDetector(),
           monBlob);
        }

        //获取系统设置
        private void GetSetting()
        {
            //从设置里获取对应的参数
            wpx = Properties.Settings.Default.GridWidth;
            hpx = Properties.Settings.Default.GridHeight;
            motionAmount = Properties.Settings.Default.MotionAmount;
        }
        //设置初始化
        private void Init()
        {
            GetSetting();
            fAnalysis = new FeatureAnalysis();

            LineAreaFeature = new Dictionary<string, CAreaFeature>();

            ////ceshi

        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            LineAreaFeature = new Dictionary<string, CAreaFeature>();

            Init();
            //// 创建视频路径
            //FileVideoSource fileSource = new FileVideoSource(@"C:\Users\weijiqiong\Desktop\card.avi");
            //// 打开视频
            //OpenVideoSource(fileSource);
        }

        private void openFile_Click(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                // 创建视频路径
                FileVideoSource fileSource = new FileVideoSource(openFileDialog.FileName);

                // 打开视频
                OpenVideoSource(fileSource);
            }
        }

        private void openLocalVideo_Click(object sender, EventArgs e)
        {
            VideoCaptureDeviceForm form = new VideoCaptureDeviceForm();


            if (form.ShowDialog(this) == DialogResult.OK)
            {
                // 打开视频
                OpenVideoSource(form.VideoDevice);
            }
        }

        private void OpenVideoSource(IVideoSource source)
        {
            // 设置鼠标忙碌
            this.Cursor = Cursors.WaitCursor;

            // 开始执行视频显示
            videoSourcePlayer.VideoSource = new AsyncVideoSource(source);
            videoSourcePlayer.Start();

            //Fps统计重置
            FpsCount.fpsReset();

            //打开计时器
            timer.Start();
            alarmTimer.Start();

            videoSource = source;

            //设置鼠标变回默认
            this.Cursor = Cursors.Default;
        }

        // 关闭以前的视频信号源
        private void CloseVideoSource()
        {
            //设置鼠标忙碌
            this.Cursor = Cursors.WaitCursor;

            // 停止当前信号
            videoSourcePlayer.SignalToStop();

            // 等待2秒，直到相机将停止
            for (int i = 0; (i < 50) && (videoSourcePlayer.IsRunning); i++)
            {
                Thread.Sleep(100);
            }
            if (videoSourcePlayer.IsRunning)
                videoSourcePlayer.Stop();

            // 停止计时
            timer.Stop();
            alarmTimer.Stop();

            motionHistory.Clear();

            //运动检测器复位
            if (detector != null)
                detector.Reset();

            videoSourcePlayer.BorderColor = Color.Black;
            this.Cursor = Cursors.Default;

            if (writer != null)
            {
                writer.Dispose();
                writer = null;
            }
        }

        //Fps显示设置
        private void timer_Tick(object sender, EventArgs e)
        {
            IVideoSource videoSource = videoSourcePlayer.VideoSource;

            if (videoSource != null)
            {
                labFps.Text = FpsCount.fpsResult(videoSource.FramesReceived).ToString("F2") + " fps";

                //显示数据
                if (tmpAllCount.Length == 0)
                {
                    tmpAllCount = new int[AllCount.Length];
                    AllCount.CopyTo(tmpAllCount, 0);
                    AllCount = new int[] { };
                    foreach (int item in tmpAllCount)
                    {
                        this.lbTime.Text = DateTime.Now.ToString("HH:mm:ss");
                        this.lbCount.Text = item.ToString();
                    }
                    tmpAllCount = new int[] { };
                }
              
                dataGridView1.DataSource = RecBlobItems;
            }
        }

        //历史数据分析（暂定）
        private void alarmTimer_Tick(object sender, EventArgs e)
        {
        }

        //
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            CloseVideoSource();
        }
        private void videoSourcePlayer_NewFrame(object sender, ref Bitmap image)
        {
            float motionLevel = detector.ProcessFrame(image);//每帧的差异值
            Rectangle[] rc = monBlob.ObjectRectangles;

            //写视频
            if ((motionLevel != 0) && (SaveVideo.Checked != false))
            {
                if ((writer != null) && (DateTime.Compare(StartTime.AddMinutes(30), DateTime.Now) < 0))
                {
                    writer.Dispose();
                    writer = null;
                }
                if (writer == null)
                {
                    DateTime date = StartTime = DateTime.Now;
                    String fileName = String.Format("{0}-{1}-{2} {3}-{4}-{5}.avi",
                        date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second);

                    try
                    {
                        // create AVI writer
                        writer = new AVIWriter("wmv3");
                        // open AVI file
                        writer.Open(fileName, image.Width, image.Height);
                    }
                    catch (ApplicationException ex)
                    {
                        if (writer != null)
                        {
                            writer.Dispose();
                            writer = null;
                        }
                    }
                }

                Monitor.Enter(this);
                writer.AddFrame(image);
                Monitor.Exit(this);
            }

            if (motionLevel == 0 || rc.Count() == 0)
            {
                return;
            }

            _lock.EnterWriteLock();

            RecBlobItems = monBlob.BlobCounter.GetObjectsInformation();//每帧区域集合

            try
            {
                //处理人数
                PeopleCount.ProcessPCount(RecBlobItems,ref AllCount);
            }
            finally
            {
                _lock.ExitWriteLock();
            }
        }

        /// <summary>
        /// 添加撞线特征区域集合
        /// </summary>
        /// <param name="strNowTime">当前时间</param>
        /// <param name="item"></param>
        /// <param name="LineNo">撞线编号</param>
        private void AddLineAreaFeature(string strNowTime, Blob item, int LineNo)
        {
            CAreaFeature cAreaFeature = new CAreaFeature()
            {
                LineOrder = LineNo,
                NowTime = strNowTime,
                areaFeature = new AreaFeature()
                {
                    Area = item.Area,
                    CCenter = new CCenter() { X = item.CenterOfGravity.X, Y = item.CenterOfGravity.Y },
                    CRectangle = new CRectangle() { X = item.Rectangle.X, Y = item.Rectangle.Y, Height = item.Rectangle.Height, Width = item.Rectangle.Width },
                    FullNess = item.Fullness
                }
            };
            LineAreaFeature.Add(Guid.NewGuid().ToString(), cAreaFeature);
        }

        //视频摄像头参数设置
        private void VideoSetting_Click(object sender, EventArgs e)
        {
            if ((videoSource != null) && (videoSource is VideoCaptureDevice))
            {
                try
                {
                    ((VideoCaptureDevice)videoSource).DisplayPropertyPage(this.Handle);
                }
                catch (NotSupportedException)
                {
                    MessageBox.Show("视频信号源不支持配置属性.", "Error",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        //线设置
        private void LineSetting_Click(object sender, EventArgs e)
        {
            FormLines lines = new FormLines();
            if (lines.ShowDialog() == DialogResult.OK)
            {
                Init();
            }
        }

        // Set Two Frames Difference motion detection algorithm
        private void twoFramesDifferenceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            motionDetectionType = 1;
            SetMotionDetectionAlgorithm(new TwoFramesDifferenceDetector());
        }
        // Set Two Frames Difference motion detection algorithm
        private void CustomFramesDifferenceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            motionDetectionType = 1;
            SetMotionDetectionAlgorithm(new CustomFrameDifferenceDetector());
        }



        // Set Simple Background Modeling motion detection algorithm
        private void simpleBackgroundModelingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            motionDetectionType = 2;
            SetMotionDetectionAlgorithm(new SimpleBackgroundModelingDetector(true, true));
        }


        // Set motion area highlighting
        private void motionAreaHighlightingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            motionProcessingType = 1;
            SetMotionProcessingAlgorithm(new MotionAreaHighlighting());
        }

        // Set motion borders highlighting
        private void motionBorderHighlightingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            motionProcessingType = 2;
            SetMotionProcessingAlgorithm(new MotionBorderHighlighting());
        }

        // Set objects' counter
        private void blobCountingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            motionProcessingType = 3;
            SetMotionProcessingAlgorithm(new BlobCountingObjectsProcessing());
        }

        // Set grid motion processing
        private void gridMotionAreaProcessingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            motionProcessingType = 4;
            SetMotionProcessingAlgorithm(new GridMotionAreaProcessing(32, 32));
        }

        // 设置新的运动检测算法
        private void SetMotionDetectionAlgorithm(IMotionDetector detectionAlgorithm)
        {
            lock (this)
            {
                detector.MotionDetectionAlgorithm = detectionAlgorithm;
                motionHistory.Clear();

                if (detectionAlgorithm is TwoFramesDifferenceDetector)
                {
                    if (
                        (detector.MotionProcessingAlgorithm is MotionBorderHighlighting) ||
                        (detector.MotionProcessingAlgorithm is BlobCountingObjectsProcessing))
                    {
                        motionProcessingType = 1;
                        SetMotionProcessingAlgorithm(new MotionAreaHighlighting());
                    }
                }
            }
        }

        // 设置新的模式处理算法
        private void SetMotionProcessingAlgorithm(IMotionProcessing processingAlgorithm)
        {
            lock (this)
            {
                detector.MotionProcessingAlgorithm = processingAlgorithm;
            }
        }

        //进出数值归零
        private void btnClearZero_Click(object sender, EventArgs e)
        {
            AllCount = new int[] { };
            lbCount.Text = "0";
        }

        //保存
        private void SaveVideo_Click(object sender, EventArgs e)
        {

            SaveVideo.Checked = !SaveVideo.Checked;
        }

        private void SearchList_Click(object sender, EventArgs e)
        {
            FormSearchList formsearch = new FormSearchList();
            //formsearch.MdiParent = this;
            if (formsearch.ShowDialog() == DialogResult.OK)
            { }
        }
    }
}